#!/bin/bash
# Job yaml can send below ENVIRONMENT VARIABLES to me
# - snapshot_id
# - upstream_repo
# - hotpatch_mode
# - pr_merge_reference_name
# mount_repo_name
# mount_repo_addr
# END ENVIRONMENT VARIABLES

. $LKP_SRC/lib/debug.sh
. $LKP_SRC/lib/upload.sh
. $LKP_SRC/lib/rpm.sh
. $LKP_SRC/lib/cache_proxy_client.sh

: "${build_user:=lkp}"

[ -n "$snapshot_id" ] || die "snapshot_id is empty"
[ -n "$upstream_repo" ] || die "upstream_repo is empty"
[ -n "$pr_merge_reference_name" ] || die "pr_merge_reference_name is empty"

die()
{
	echo "$@"
	[ -n "$sff" ] && sleep ${sff}
	exit 99
}

in_array()
{
	local arr=$1
	for item in ${arr[*]};
	do
		[ "$item" == "$2" ] && return 0
	done

	return 1
}

git_clone()
{
        local depth=${3:-100}
        for i in {1..10}
        do
                [[ "${i}" -gt 1 ]] && sleep 6
                git clone -q ${1} --depth=${depth} 2>/dev/null || continue
                return 0
        done
        return 1
}

git_lfs_clone()
{
        local depth=${3:-100}
        for i in {1..10}
        do
                [[ "${i}" -gt 1 ]] && sleep 6
                git lfs clone ${1} -b ${2} --depth=${depth} 2>/dev/null || continue
                return 0
        done
        return 1
}

install_gcc_secure()
{
	yum install -y gcc_secure
}

sync_system_rpms()
{
	if [[ "$mount_repo_name" =~ "lastest_repo" ]]; then
		dnf distro-sync -y --allowerasing --repo 0
		local sync_repo_file="/etc/yum.repos.d/openEuler.repo"
		[ -e "${sync_repo_file}" ] && rm -rf "${sync_repo_file}"
	fi
}

preinstall_packages()
{
	[ -n "$preinstall" ] || return
	yum install -y ${preinstall}
}

statistic_info()
{
	echo "==========================rpm -qa==========================" >> /tmp/statistic_info
	rpm -qa|sort >> /tmp/statistic_info
	echo "==========================export==========================" >> /tmp/statistic_info
	export|sort >> /tmp/statistic_info
	echo "==========================uname -a==========================" >> /tmp/statistic_info
	uname -a >> /tmp/statistic_info
	echo "==========================rpm --showrc==========================" >> /tmp/statistic_info
	rpm --showrc >> /tmp/statistic_info
	echo "==========================rpmsepc -P==========================" >> /tmp/statistic_info
	rpmspec -P ${spec_dir}/${spec_file_name} >> /tmp/statistic_info
	echo "==========================os-release==========================" >> /tmp/statistic_info
	cat /etc/os-release >> /tmp/statistic_info
	upload_one_curl /tmp/statistic_info ${result_root}
}

install_charset()
{
	yum install -y glibc-all-langpacks glibc-locale-archive
}


show_rpm_files()
{
	find ${hotpatch_dir} -type f -name "*.rpm"
}

show_src_rpm_files()
{
	find ${hotpatch_src_dir} -type f -name "*.src.rpm"
}

upload_rpm_pkg()
{
	local rpm_file
	for rpm_file in $(show_rpm_files)
	do
		upload_one_curl ${rpm_file} ${rpm_dest}
	done

	local src_rpm_file
	for src_rpm_file in $(show_src_rpm_files)
	do
		upload_one_curl ${src_rpm_file} ${rpm_dest}
	done

	upload_one_curl ${updateinfo_path} ${rpm_dest}
	[ $os_arch == x86_64 ] && upload_one_curl ${updateinfo_src_path} ${rpm_dest}
}

get_rpms_build_env()
{

	OLDIFS=$IFS
	IFS=$'\n'
	arr=($(rpm -qa --qf '%{NAME} %{PKGID}\n'))
	IFS=$OLDIFS
	rpms_build_env=/tmp/rpms_build_env

	for i in ${!arr[@]}
	do
		cc=(${arr[$i]})
		cat >> "$rpms_build_env" <<-EOF
		{"name": "${cc[0]}", "pkgid": "${cc[1]}"},
		EOF
	done
	sed -i '$ s/.$//' "$rpms_build_env"
}

get_rpms_pkgid()
{
	brpms_pkgid=$(find ${hotpatch_dir} -type f -name "*.rpm" | xargs rpm -q --qf '\{\"name\":\"%{NAME}\",\"pkgid\":\"%{PKGID}\"\},\n')
	srpms_pkgid=$(find ${hotpatch_src_dir} -type f -name "*.rpm" | xargs rpm -q --qf '\{\"name\":\"%{NAME}\", \"pkgid\":\"%{PKGID}\"\},\n')
	rpms_pkgid=${brpms_pkgid}${srpms_pkgid}
}

get_rpms_detail()
{
        rpms_detail=/tmp/rpms_detail.json
        for full_path in "${hotpatch_dir}" "${hotpatch_src_dir}"
        do
                for file in $(find ${full_path} -type f -name "*.rpm")
                do
                        requires=$(rpm -q ${file} --requires | awk '{printf"\"%s\",", $0}')
                        provides=$(rpm -q ${file} --provides | awk '{printf"\"%s\",", $0}')
                        cat >> "$rpms_detail" <<-EOF
			"${file##*/}":{
			"Title": "$(echo $(echo $(rpm -q ${file} --qf %{SUMMARY}) | sed $'s/\"/\'/g') | sed $'s/\\\\//g')",
			"Description": "$(echo $(echo $(rpm -q ${file} --qf %{DESCRIPTION}) | sed $'s/\"/\'/g') | sed $'s/\\\\//g')",
			"Size": "$(rpm -q ${file} --qf %{SIZE})",
			"Architecture": "$(rpm -q ${file} --qf %{ARCH})",
			"Version": "$(rpm -q ${file} --qf %{VERSION})",
			"Release": "$(rpm -q ${file} --qf %{RELEASE})",
			"Build Time": "$(rpm -q ${file} --qf %{BUILDTIME})",
			"requires": [${requires%?}],
			"provides":[${provides%?}]},
			EOF
                done
        done
        sed -i '$ s/.$//' "$rpms_detail"
}

get_rpms_install()
{
	rpms_install=/tmp/install.json

	# texlive-*
	if [[ "$package_name" =~ "texlive-" ]]; then
		res="Dependencies resolved."
	else
		res=$(find ${hotpatch_dir} -type f -name "*.rpm" | xargs yum install --assumeno 2>&1)
	fi
	echo "$res" | grep "no arguments given for query"
	res="Dependencies resolved."

	echo "$res" | grep "Dependencies resolved."
	if [ $? == 0 ]; then
		echo "\"status\": \"success\", \"missing_deps\": {}" >> ${rpms_install}
	fi
	miss_deps=$(echo "$res" | grep '\- nothing provides' | awk -F '- nothing provides ' '{printf"\"%s\",",$2}')
	[ -n "$miss_deps" ] && {
		echo "\"status\": \"failed\", \"missing_deps\": [${miss_deps%?}]" >> ${rpms_install}
	}
}

create_rpm_json()
{
	get_rpms_pkgid
	get_rpms_detail
	get_rpms_install
	get_rpms_build_env

	rpm_json=/tmp/${os_project}_${os_variant}_${os_arch}_${snapshot_id}_${id}.json
	cat > "$rpm_json" <<-EOF
	{
		"job_id": "${id}",
		"build_id": "${build_id}",
		"build_type": "${build_type}",
		"start_build_time": "${start_build_time}",
		"rpm_path": "${rpm_dest}",
		"os_variant": "${os_variant}",
		"os_project": "${os_project}",
		"snapshot_id": "${snapshot_id}",
		"submit_time": "${submit_time}",
		"architecture": "${os_arch}",
		"rpms": [
			${rpms_pkgid%?}
		],
		"install": {
			$(cat ${rpms_install})
		},
		"rpms_detail": {
			$(cat ${rpms_detail})
		},
		"rpms_build_env": [
			$(cat ${rpms_build_env})
		]
	}
	EOF
}

upload_rpm_json()
{
	create_rpm_json
	upload_one_curl "$rpm_json" "/repositories/new-jobs/"
}

init_build_env()
{
	hostname dc-64g.compass-ci
	echo "export TERM=xterm-256color" >> /etc/profile
	echo "export TZ=Asia/Shanghai" >> /etc/profile
	source /etc/profile
	# gcc_secure use the file
	echo "${repo_name}.spec" > /.build.command
	chmod 775 /.build.command
}

init_hotpatch_workspace()
{
	rpm_dest="/repositories/${os_project}/${os_variant}/${os_arch}/history/${snapshot_id}/steps/upload/${id}/"
	rpmdev_dir=/root/rpmbuild
	root_path=/hotpatch_pr
	mkdir -p ${root_path}

	hotpatch_cicd=/hotpatch_cicd
	shell_path=/home/jenkins/ci_check
	patch_dir=${hotpatch_cicd}/patch_dir
	hotpatch_dir=${hotpatch_cicd}/hotpatch_dir
	update_info_file=${hotpatch_cicd}/update_info
	updateinfo_path=${hotpatch_cicd}/updateinfo_path
	hotpatch_src_dir=${hotpatch_cicd}/hotpatch_src_dir
	metadata_path=${hotpatch_cicd}/hot-patch_metadata
	modify_version_file=${hotpatch_cicd}/modify_version
	updateinfo_src_path=${hotpatch_cicd}/updateinfo_src_path

	release_path=/repo/openeuler/${comment_branch}
	hotpatch_update_src_path=hotpatch_update/source/Packages

	mkdir -p ${patch_dir} ${hotpatch_dir} ${hotpatch_src_dir}
}

parse_update_params()
{
	local update_info_file=/tmp/update_info
	local mode_xml="./$(git diff --name-status HEAD~1 HEAD~0 | grep hotmetadata_ | awk '{print $NF}')"
	[ -z "$mode_xml" ] && die "find hotmetadata_${mode}.xml failed in $(pwd)"

	python3 ${LKP_SRC}/lib/create_hotpatch_update_info.py -i ${mode_xml} -o ${update_info_file} -m ${mode}
	[ -f "$update_info_file" ] || die "create update info file error, mode_xml: ${mode_xml}."

	cve_type=$(cat ${update_info_file} | grep cve_type: | sed 's/^.*cve_type: //g')
	issue_id=$(cat ${update_info_file} | grep issue_id: | sed 's/^.*issue_id: //g')
	patch_name=$(cat ${update_info_file} | grep patch_name: | sed 's/^.*patch_name: //g')
	curr_version=$(cat ${update_info_file} | grep curr_version: | sed 's/^.*curr_version: //g')
	curr_release=$(cat ${update_info_file} | grep curr_release: | sed 's/^.*curr_release: //g')
	reference_id=$(cat ${update_info_file} | grep reference-id: | sed 's/^.*reference-id: //g')
	reference_href=$(cat ${update_info_file} | grep reference-href: | sed 's/^.*reference-href: //g')
	reference_type=$(cat ${update_info_file} | grep reference-type: | sed 's/^.*reference-type: //g')
	hotpatch=$(cat ${update_info_file} | grep patch: | sed 's/^.*patch: //g')

        mkdir ${hotpatch}
        all_patch=""
        for patch in ${hotpatch//,/ }
        do
                cp $repo_path/$patch ${patch_dir}
                all_patch="$all_patch ${patch_dir}/$patch"
        done

}

git_fetch_pr_repo()
{
        git config --global http.lowSpeedLimit 0
        git config --global http.lowSpeedTime 3600
        git config --global lfs.activitytimeout 3600

        local url="git://${GIT_SERVER}/${upstream_repo}"

        metadata_path=${upstream_repo##*/}
        metadata_path="/${metadata_path%.git}"

        git_clone "${url} ${metadata_path}" || die "clone git repo failed, url: ${url}"

        cd "${metadata_path}"
        pr_id=$(echo $pr_merge_reference_name | awk '{split($0,a,"/");print a[3]}')
        local lpr="pr_${pr_id}"

        git fetch origin "pull/${pr_id}/head:${lpr}"
        git checkout -q "${lpr}" || die "checkout git repo ${package_name} to ${lpr} failed"
}

parse_path_info()
{
        cd "${metadata_path}"
	mode=$(echo $(git diff --name-status HEAD~1 HEAD~0) | sed 's/.*hotmetadata_\([^/]*\)\.xml.*/\1/')
        patch_path=$(git diff --name-status HEAD~1 HEAD~0 | grep "\.patch" | head -n 1 | awk -F ' ' '{print $2}')
        hotmetadata_path=$(git diff --name-status HEAD~1 HEAD~0 | grep "hotmetadata_${mode}.xml" | awk -F ' ' '{print $2}')

        if [[ ${hotmetadata_path} && ! ${patch_path} ]]; then
                repo_path=${hotmetadata_path%/*}/patch
        fi
        if [[ !${hotmetadata_path} && ${patch_path} ]]; then
                repo_path=${patch_path%/*}
                hotmetadata_path=${repo_path%/*}/hotmetadata_${mode}.xml
        fi

        repo_path=${metadata_path}/${repo_path}
        hotmetadata_xml=${metadata_path}/${hotmetadata_path}
        repo_name=$(echo ${hotmetadata_path} | awk -F '/' '{print $2}')
        comment_branch=$(echo ${hotmetadata_path} | awk -F '/' '{print $1}')
}

download_rpms()
{
	cd ${root_path} || die "there is no root_path: ${root_path}"
	echo "hotmetadata xml contents:"
	cat ${hotmetadata_xml}
	src_rpm_url=$(cat ${hotmetadata_xml} | grep SRC_RPM | sed 's/^.*<SRC_RPM>//g' | sed 's/<\/SRC_RPM>.*$//g'| \
		awk -F " " 'END {print}')
	echo "parse src rpm url: ${src_rpm_url}"
	wget -q ${src_rpm_url} -P ${root_path} || die "wget src rpm url failed: ${src_rpm_url}"
	if [[ $os_arch == "x86_64" ]]; then
		debug_url=$(cat ${hotmetadata_xml} | grep Debug_RPM_X86_64 | sed 's/^.*<Debug_RPM_X86_64>//g' | \
			sed 's/<\/Debug_RPM_X86_64>.*$//g'|awk -F " " 'END {print}')
	elif [[ $os_arch == "aarch64" ]]; then
		 debug_url=$(cat ${hotmetadata_xml} | grep Debug_RPM_Aarch64 | sed 's/^.*<Debug_RPM_Aarch64>//g' | \
			sed 's/<\/Debug_RPM_Aarch64>.*$//g'|awk -F " " 'END {print}')
	fi
	wget -q ${debug_url} -P ${root_path} || die "wget debug url failed: ${debug_url}"
}

yum_build_dep()
{
	[ -n "$prefer" ] && yum install -y ${prefer}
	rpm -ivh ${source_file}
	yum-builddep -y /root/rpmbuild/SPECS/*.spec 2>&1 || die "failed to solve dependencies"
}

syscare_build()
{
	install_charset
	install_gcc_secure
	preinstall_packages
	sync_system_rpms

	source_file=${src_rpm_url##*/}
	debug_file=${debug_url##*/}

	yum_build_dep

	if [[ $mode == "ACC" ]]; then
		patch_name="ACC"
	else
		patch_name=`echo ${patch_name}|sed 's/-/_/g'`
	fi

	/usr/bin/upatchd -d

	syscare build --jobs 8 --patch-name ${patch_name} --patch-version ${curr_version} --patch-release ${curr_release} \
	        --source ${source_file} --debuginfo ${debug_file} --output ${hotpatch_dir} --patch ${all_patch} || die "syscare build error"

	hotpatch_src_filename=$(ls ${hotpatch_dir}/*.src.rpm)
	mv ${hotpatch_src_filename} /${hotpatch_src_dir}
	statistic_info
}

generate_updateinfo()
{
	hotpatch_file=$(ls ${hotpatch_dir}/patch*.rpm)
	updateinfo_path=${hotpatch_file%.*}.xml

	gen-updateinfo ${cve_type} "${issue_title}" ${issue_id} --reference-type ${reference_type} --reference-id ${reference_id} \
	        --reference-href ${reference_href} --issued-date ${issue_date} --package-dir ${hotpatch_dir} --output-path ${updateinfo_path}

	if [[ $os_arch == "x86_64" ]]; then
		updateinfo_src_path=/${hotpatch_src_filename%.*}.xml
		gen-updateinfo ${cve_type} "${issue_title}" ${issue_id} --reference-type ${reference_type} --reference-id ${reference_id} \
		--reference-href ${reference_href} --issued-date ${issue_date} --package-dir ${hotpatch_src_dir} --output-path ${updateinfo_src_path}
	fi
}

upload_hotpatch()
{
	upload_rpm_pkg
	upload_rpm_json
}


main()
{
	init_hotpatch_workspace
	git_fetch_pr_repo
	parse_path_info
	init_build_env
	parse_update_params
	download_rpms
	syscare_build
	generate_updateinfo
	upload_hotpatch
}

main
